<?php
/**
 * Created by PhpStorm.
 * User: peter
 * Date: 2018/10/19
 * Time: 下午3:14
 */

namespace app\activity\logic;


use app\model\AccountCapitalFlow;
use app\model\ActivityOrder;
use app\model\ActivityOrderAttach;
use app\model\Bill;
use EasyWeChat\Factory;
use extend\Functions;
use extend\STATUS_CODE;
use think\facade\Env;

class Pay
{
    /**
     * @purpose 获取支付凭证
     * @param string $order_no
     * @param int $uid
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function voucher(string $order_no, int $uid, int $pay_method)
    {
        if (!$order_no) {
            return Functions::result(
                STATUS_CODE::PARAMETER_ERROR,
                '参数错误'
            );
        }
        $order        = new ActivityOrder();
        $member       = new \app\model\Member();
        $order_attach = new ActivityOrderAttach();
        $order->startTrans();
        $member_info = $member
            ->with('wechat')
            ->where('uid', $uid)
            ->find();
        if (!$member_info) {
            return Functions::result(
                STATUS_CODE::FAIL,
                '请登录...!'
            );
        }
        // 获取订单信息
        $order_info = $order
            ->with(['activity' => function ($query) {
                $query->field('id,title');
            }])
            ->where([
                ['order_no', '=', $order_no],
                ['uid', '=', $uid],
            ])
            ->lock(true)
            ->field('id,activity_id,group_stage_id,status,order_no,create_at')
            ->find();
        if (!$order_info) {
            $order->rollback();
            return Functions::result(
                STATUS_CODE::FAIL,
                '订单不存在...!'
            );
        }
        if ($order_info->status !== 1) {
            $order->rollback();
            return Functions::result(
                STATUS_CODE::FAIL,
                '订单状态错误'
            );
        }
        // 获取支付金额
        $total_price = $order_attach
            ->where([
                ['order_id', '=', $order_info->id],
                ['status', '=', 1],
            ])
            ->sum('price');

        switch ($pay_method) {
            case 1: // 微信支付
                $voucher = $order_info->order_no . '-' . Functions::random(4);
                RE_VOUCHER:
                $voucher = $voucher = $order_info->order_no . '-' . Functions::random(4);
                if ($order->where(['pay_voucher' => $voucher])->count(1) > 0) {
                    goto RE_VOUCHER;
                }
                $order->isUpdate(true)->save(['pay_voucher' => $voucher], ['id' => $order_info->id]);
                $app                 = Factory::payment(config('wechat.payment.official_account'));
                $data                = [
                    'body'         => '欢乐中国网-活动报名!',
                    'trade_type'   => 'JSAPI',
                    'out_trade_no' => $voucher,
                    'total_fee'    => $total_price,
                    'openid'       => cookie('pay_openid'),
                    'attach'       => $member_info->uuid,
                ];
                $result              = $app->order->unify($data);
                $result              = $app->jssdk->sdkConfig($result['prepay_id']);
                $result['timeStamp'] = $result['timestamp'];
                unset($result['timestamp']);
                $order->commit();
                return Functions::result([
                    'pay_method' => $pay_method,
                    'voucher' => $result,
                ]);
                break;
            case 3: // 余额支付
                if ($member_info->balance < $total_price) {
                    return Functions::result(
                        STATUS_CODE::FAIL,
                        '余额不足'
                    );
                }
                $balance_result = $member
                    ->where('uid', $uid)
                    ->setDec('balance', $total_price);

                $update_data               = [];
                $update_data['status']     = 99;
                $update_data['pay_time']   = time(); // strtotime($send_pay_date);
                $update_data['pay_money']  = $total_price;
                $update_data['pay_method'] = 10;
                // 更新订单状态
                $order_result = $order
                    ->isUpdate(true)
                    ->save($update_data, ['id' => $order_info->id]);
                // 更新订单附表状态
                $order_attach_result = $order_attach
                    ->isUpdate(true)
                    ->save(['status' => 99], ['order_id' => $order_info->id, 'status' => 1]);
                // 记录账户资金流水
                $account_capital_flow = AccountCapitalFlow::M()
                    ->data([
                        'uid'          => $uid,
                        'quota'        => $total_price,
                        'type'         => 2,
                        'balance' => ($member_info->balance - $member_info->frozen) - $total_price,
                        'descriptions' => '参加活动【' . $order_info->activity->title . '】',
                    ])
                    ->save();
                // 记录账单活动支付账单
                $bill_result = Bill::addToBill(
                    $uid,
                    1,
                    $order_no,
                    $total_price,
                    10,
                    '报名活动: 【' . $order_info->activity->title . '】'
                );
                if ($balance_result &&
                    $order_result &&
                    $order_attach_result &&
                    $account_capital_flow &&
                    $bill_result) {
                    $order->commit();
                    return Functions::result(
                        STATUS_CODE::SUCCESS,
                        [
                            'pay_method' => $pay_method
                        ]
                    );
                }
                return Functions::result(
                    STATUS_CODE::FAIL,
                    '余额支付失败'
                );
                break;
        }
    }

    /**
     * @purpose app支付获取支付凭证
     * @param string $order_no
     * @param int $uid
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function appPayVoucher(string $order_no, int $pay_type = 1, int $uid)
    {
        if (!$order_no) {
            return Functions::result(
                STATUS_CODE::PARAMETER_ERROR,
                '参数错误'
            );
        }
        $order        = new ActivityOrder();
        $member       = new \app\model\Member();
        $order_attach = new ActivityOrderAttach();
        $order->startTrans();
        $member_info = $member
            ->with('wechat')
            ->where('uid', $uid)
            ->find();
        if (!$member_info) {
            return Functions::result(
                STATUS_CODE::FAIL,
                '请登录...!'
            );
        }
        // 获取订单信息
        $order_info = $order
            ->with(['activity' => function ($query) {
                $query->field('id,title');
            }])
            ->where([
                ['order_no', '=', $order_no],
                ['uid', '=', $uid],
            ])
            ->lock(true)
            ->field('id,activity_id,group_stage_id,status,order_no,create_at')
            ->find();
        if (!$order_info) {
            $order->rollback();
            return Functions::result(
                STATUS_CODE::FAIL,
                '订单不存在...!'
            );
        }
        if ($order_info->status !== 1) {
            $order->rollback();
            return Functions::result(
                STATUS_CODE::FAIL,
                '订单状态错误'
            );
        }
        // 获取支付金额
        $total_price = $order_attach
            ->where([
                ['order_id', '=', $order_info->id],
                ['status', '=', 1],
            ])
            ->sum('price');

        switch ($pay_type) {
            case 1: // 微信支付
                $voucher = $order_info->order_no . '-' . Functions::random(4);
                RE_VOUCHER:
                $voucher = $voucher = $order_info->order_no . '-' . Functions::random(4);
                if ($order->where(['pay_voucher' => $voucher])->count(1) > 0) {
                    goto RE_VOUCHER;
                }
                $order->isUpdate(true)->save(['pay_voucher' => $voucher], ['id' => $order_info->id]);
                $result              = Functions::wechatAppPay([
                    'body'         => '欢乐中国网活动报名',
                    'detail'       => '参加活动【' . $order_info->activity->title . '】',
                    'out_trade_no' => $voucher,
                    'total_fee'    => $total_price,
                    'attach'       => $member_info->uuid,
                    'trade_type'   => 'APP',
                ]);
                $result['timestamp'] = time();
                $order->commit();
                return Functions::result(
                    STATUS_CODE::SUCCESS,
                    [
                        'pay_type' => $pay_type,
                        'voucher'  => $result,
                    ]
                );
                break;
            case 2: // 支付宝支付
                include Env::get('root_path') . 'extend/alipay/AopSdk.php';
                include Env::get('root_path') . 'extend/alipay/aop/request/AlipayTradeAppPayRequest.php';
                $aop                        = new \AopClient();
                $aop->gatewayUrl            = 'https://openapi.alipay.com/gateway.do';
                $aop->appId                 = config('alipay.app.appid');
                $aop->rsaPrivateKey         = config('alipay.app.private_key');
                $aop->format                = "json";
                $aop->charset               = "UTF-8";
                $aop->signType              = "RSA";
                $aop->alipayrsaPublicKey    = config('alipay.app.public_key');
                $content                    = [];
                $content['body']            = '欢乐中国网活动报名';
                $content['subject']         = '参加活动【' . $order_info->activity->title . '】';
                $content['out_trade_no']    = $order_info->order_no;
                $content['timeout_express'] = '30m';
                $content['total_amount']    = $total_price / 100;
                $content['product_code']    = 'QUICK_MSECURITY_PAY';
                $request                    = new \AlipayTradeAppPayRequest();
                $request->setNotifyUrl('http://server.enjoychina.cc/activity-api/activity.activity.alipay.notify.async');
                $request->setBizContent(json_encode($content));
                $response = $aop->sdkExecute($request);
                return Functions::result(
                    STATUS_CODE::SUCCESS,
                    [
                        'pay_type' => $pay_type,
                        'voucher'  => $response,
                    ]
                );
                break;
            case 3:
                if ($member_info->balance < $total_price) {
                    return Functions::result(
                        STATUS_CODE::FAIL,
                        '余额不足'
                    );
                }
                $balance_result = $member
                    ->where('uid', $uid)
                    ->setDec('balance', $total_price);

                $update_data               = [];
                $update_data['status']     = 99;
                $update_data['pay_time']   = time(); // strtotime($send_pay_date);
                $update_data['pay_money']  = $total_price;
                $update_data['pay_method'] = 10;
                // 更新订单状态
                $order_result = $order
                    ->isUpdate(true)
                    ->save($update_data, ['id' => $order_info->id]);
                // 更新订单附表状态
                $order_attach_result = $order_attach
                    ->isUpdate(true)
                    ->save(['status' => 99], ['order_id' => $order_info->id, 'status' => 1]);
                // 记录账户资金流水
                $account_capital_flow = AccountCapitalFlow::M()
                    ->data([
                        'uid'          => $uid,
                        'quota'        => $total_price,
                        'balance' => ($member_info->balance - $member_info->frozen) - $total_price,
                        'type'         => 2,
                        'descriptions' => '参加活动【' . $order_info->activity->title . '】',
                    ])
                    ->save();
                // 记录账单活动支付账单
                $bill_result = Bill::addToBill(
                    $uid,
                    1,
                    $order_no,
                    $total_price,
                    10,
                    '报名活动: 【' . $order_info->activity->title . '】'
                );
                if ($balance_result &&
                    $order_result &&
                    $order_attach_result &&
                    $account_capital_flow &&
                    $bill_result) {
                    $order->commit();
                    return Functions::result(
                        STATUS_CODE::SUCCESS,
                        [
                            'pay_type' => $pay_type
                        ]
                    );
                }
                return Functions::result(
                    STATUS_CODE::FAIL,
                    '余额支付失败'
                );
        }
    }
}